package org.ns.tomdog.config;

import com.sun.istack.internal.NotNull;
import org.ns.tomdog.config.error.ServerConfigParseException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;

public abstract class XmlConfigParse {
    protected ClassLoader classLoader;
    protected Document document;

    public XmlConfigParse(@NotNull File xmlConfigPath, @NotNull ClassLoader classLoader) throws ServerConfigParseException {
        this.classLoader = classLoader;
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            this.document = db.parse(xmlConfigPath);
        } catch (Exception e) {
            throw new ServerConfigParseException(e);
        }

    }

    public abstract void parse();

    public Document getDocument() {
        return document;
    }
/*
    <servlet name="" class="">
        <mapper path=""/>
    </servlet>

 */
    protected <T>Class<T> getClass(Element element, Class<T> type) throws ClassNotFoundException {
        return getClass(element, type, classLoader);
    }

    protected <T>Class<T> getClass(Element element, Class<T> type, ClassLoader classLoader) throws ClassNotFoundException {
        String aClass = element.getAttribute("class");
        return (Class<T>)classLoader.loadClass(aClass);
    }

    protected <T>Class<T> getClass(String className, Class<T> type) throws ClassNotFoundException {
        return (Class<T>)classLoader.loadClass(className);
    }

    protected String getAttribute(Element element, String name, String def) {
        String value = element.getAttribute(name);
        if (value == null || (value = value.trim()).isEmpty()) {
            return def;
        }
        return value;
    }

    protected void parse(String tagName, Element element, Consumer<Element> consumer) {
        if (element == null) {
            element = document.getDocumentElement();
        }
        NodeList elements = element.getElementsByTagName(tagName);
        for (int i = 0; i < elements.getLength(); i++) {
            Element node = (Element) elements.item(i);
            consumer.accept(node);
        }
    }
    protected <T>T parseFrist(String tagName, Element element, Function<Element, T> consumer) {
        if (element == null) {
            element = document.getDocumentElement();
        }
        NodeList elements = element.getElementsByTagName(tagName);
        for (int i = 0; i < elements.getLength(); i++) {
            Element node = (Element) elements.item(i);
            Object value = consumer.apply(node);
            if (value != null) {
                return (T)value;
            }
        }
        return null;
    }

    protected <T> List<T> parseToList(String tagName, Element element, Function<Element, T> consumer) {
        if (element == null) {
            element = document.getDocumentElement();
        }
        List<T> list = new ArrayList<>();
        NodeList elements = element.getElementsByTagName(tagName);
        for (int i = 0; i < elements.getLength(); i++) {
            Element node = (Element) elements.item(i);
            T value = consumer.apply(node);
            if (value != null) {
                list.add(value);
            }
        }
        return list;
    }

    public ClassLoader getClassLoader() {
        return classLoader;
    }

}
